package com.nokia.desertstorm.nodeburst
{
	import caurina.transitions.Equations;
	import caurina.transitions.Tweener;
	import caurina.transitions.properties.TextShortcuts;
	
	import com.nokia.desertstorm.audio.SoundProvider;
	import com.nokia.desertstorm.events.NodeEvent;
	import com.nokia.desertstorm.parallax.Landscape;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	
	public class NodeBurst extends Sprite
	{
		private var _node:Node = new Node();
		private var _cluster:Sprite = _node.getChildByName("cluster") as Sprite;
		private var _limit:Number;
		private var _arrows:Array = new Array();
		private var _sections:Array;
		private var _buildInCounter:Number = 0;
		private var _category:Number;
		
		private static const TEXT_FIELD_SPRITE:String = "textfield";
		private static const TEXT:String = "text";
		private static const EMBEDDED:String = "embedded"
		private static const HIT_TEST:String = "hittester";
				
		public function NodeBurst(limit:Number, sections:Array, category:Number)
		{
			TextShortcuts.init();
			_limit = limit;
			_sections = sections;
			_category = category;
			addChild(_node);
			createArrows();
		}
		
		public function openNode():void
		{
			Tweener.addTween(_cluster, {scaleX:1, scaleY:1, time:0.5, onComplete:animateArrows});
		}
		
		private function glowIn():void
		{
			Tweener.addTween(_node, {scaleX:1.3, scaleY:1.3, transition:Equations.easeOutCubic, time:0.5, onComplete:glowOut});
		}
		
		private function glowOut():void
		{
			Tweener.addTween(_node, {scaleX:1, scaleY:1, time:0.5, transition:Equations.easeInCubic, onComplete:glowIn});
		}
		
		public function closeNode():void
		{
			for(var i:Number = 0; i < _limit; i++)
			{
				var arrow:Arrow = _arrows[i].instance;
				var textHolderSprite:Sprite = arrow.getChildByName(TEXT_FIELD_SPRITE) as Sprite;
				var text:TextField = textHolderSprite.getChildByName(TEXT) as TextField;
				Tweener.addTween(text, {_text:"", time:0.5});
				var inner:Sprite = arrow.getChildByName(EMBEDDED) as Sprite;
				Tweener.addTween(inner, {width:0, time:0.5, transition:Equations.easeOutExpo});
				
				//Don't forget to remove the event listeners
				textHolderSprite.removeEventListener(MouseEvent.CLICK, onMouseClick);
				textHolderSprite.removeEventListener(MouseEvent.ROLL_OVER, onRollOver);
				textHolderSprite.removeEventListener(MouseEvent.ROLL_OUT, onRollOut);
			}
		}
		
		private function createArrows():void
		{	
			for(var i:Number = 0; i < _limit; i++)
			{
				var arrow:ArrowWrapper = new ArrowWrapper(_category,i);
				_arrows.push(arrow);
			}	
		}
		
		private function animateArrows():void
		{
			_buildInCounter = 0;
			var division:Number = 360/_limit;
			for(var i:Number = 0; i < _limit; i++)
			{
				var arrow:Arrow = _arrows[i].instance;
				var textHolderSprite:Sprite = arrow.getChildByName(TEXT_FIELD_SPRITE) as Sprite;
				var inner:Sprite = arrow.getChildByName(EMBEDDED) as Sprite;
				var hitter:Sprite = textHolderSprite.getChildByName(HIT_TEST) as Sprite;
				hitter.width = 0;
				hitter.rotation = 0;
				
				textHolderSprite.buttonMode = true;
				textHolderSprite.addEventListener(MouseEvent.CLICK, onMouseClick);
				textHolderSprite.addEventListener(MouseEvent.ROLL_OVER, onRollOver);
				textHolderSprite.addEventListener(MouseEvent.ROLL_OUT, onRollOut);
				textHolderSprite.mouseChildren = false;
				
				inner.width = 1;
				arrow.x = _node.x;
				arrow.y = _node.y;
				var w:Number = Math.random()* 50 + 30;
				Tweener.addTween(inner, {	width:w, 
											time:0.5, 
											delay:i/10, 
											transition:Equations.easeOutExpo, 
											onStart:playSound, 
											onComplete:textIn,
											onCompleteParams:[i]});
				arrow.rotation = i*division - division*Math.random();
				textHolderSprite.x = w + 30;
				textHolderSprite.y = 0;
				textHolderSprite.rotation = -arrow.rotation; 
				addChild(_arrows[i]);
			}
		}
		
		//This formula is taken from AcrionScript 3.0 Animation by Kieth Peters
		private function detectArrowCollision():void
		{
			var iterants:Number = _arrows.length;
			for(var i:Number = 0; i < iterants - 1; i++)
			{
				var spriteA:Sprite = _arrows[i].instance.getChildByName(TEXT_FIELD_SPRITE);
				for(var j:Number = i + 1; j < iterants; j++)
				{
					var spriteB:Sprite =  _arrows[j].instance.getChildByName(TEXT_FIELD_SPRITE);
					if(spriteA.hitTestObject(spriteB))
					{
						//detect the collision and then call the appropriate recursive adjustor function 
						var p:Point = new Point(spriteA.x, spriteA.y);
						var p2:Point = new Point(spriteB.x, spriteA.y);
						if(spriteA.localToGlobal(p2).y > spriteB.localToGlobal(p2).y){
							adjustPosUp(spriteA, spriteB);
						}else{
							adjustPosDown(spriteA, spriteB);
						}
					}
				}
			}
		}
		
		private function adjustPosUp(spriteA:Sprite, spriteB:Sprite):void
		{
			spriteA.y -= 5;
			spriteA.hitTestObject(spriteB) ? adjustPosUp(spriteA, spriteB) : "";
			adjustPointer();
		}
		
		private function adjustPosDown(spriteA:Sprite, spriteB:Sprite):void
		{
			spriteA.y -= 5;
			spriteA.hitTestObject(spriteB) ? adjustPosDown(spriteA, spriteB) : "";
			adjustPointer();
		}
		
		private function adjustPointer():void
		{
			//adjust arrow position so that it is always pointing at the associative text field after collision
		}
		
		private function textIn(section:Number):void
		{			
			var textHolderSprite:Sprite = _arrows[section].instance.getChildByName(TEXT_FIELD_SPRITE) as Sprite;
			var text:TextField = textHolderSprite.getChildByName(TEXT) as TextField;
			var hitter:Sprite = textHolderSprite.getChildByName(HIT_TEST) as Sprite;
			text.mouseEnabled = false;
			text.text = "";
			Math.abs(textHolderSprite.rotation) > 90 ? text.autoSize = TextFieldAutoSize.RIGHT : text.autoSize = TextFieldAutoSize.LEFT;
			Math.abs(textHolderSprite.rotation) > 90 ? hitter.rotation = 180 : "";
			Tweener.addTween(text, {_text:""+_sections[section], time:0.5, onComplete:sizeHitArea, onCompleteParams:[hitter, text]});
		}
		
		private function sizeHitArea(sprite:Sprite, textfield:TextField):void
		{
			_buildInCounter++;
			sprite.width = textfield.width;
			if(_buildInCounter == _arrows.length-1)
			{
				detectArrowCollision();
			}
		}
		
		private function onMouseClick(e:MouseEvent):void
		{
			//trace(ProjectData.data.group.category[1].section[1]);
			//var arrow:ArrowWrapper = e.target.parent.parent as ArrowWrapper;
			var arrow:ArrowWrapper = e.target.parent.parent as ArrowWrapper;
		    var category:Number = arrow.category;
			var section:Number = arrow.section;
			dispatchEvent(new NodeEvent(NodeEvent.NODE_CLICKED, category, section));	
		}
		
		private function onRollOver(e:MouseEvent):void
		{
			//Wish list to include magnetic attraction
			Landscape.mouseScrollEnabled = false;
		}
		
		private function onRollOut(e:MouseEvent):void
		{
			//Sprite(e.target).removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			Landscape.mouseScrollEnabled = true;
		}
		
		private function onMouseMove(e:MouseEvent):void
		{
			//create a weak attraction to be able to move nodes with mouse
		}
		
		private function playSound():void
		{
			SoundProvider.getInstance().playRolloverSound();
		}
		
	}
}